package com.onluy.frameworkcloud.tools.utils;
import com.alibaba.fastjson.JSON;
import com.onluy.frameworkcloud.base.AppWalkService;
import org.apache.commons.net.ftp.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;

public class FtpUtil  extends AppWalkService {


    static Logger logger =   LoggerFactory.getLogger(FtpUtil.class);


    private  FtpConfig ftpConfig;

    public  FtpUtil(FtpConfig ftpConfig){
        this.ftpConfig=ftpConfig;
    }


    private  ThreadLocal<FTPClient>  ftpClientThreadLocal=new  ThreadLocal<FTPClient> ();




    private FTPClient getConnectionFTP() throws Exception {
        logger.info("getConnectionFTP  start!!!!!!!");
        FTPClient fTPClient=ftpClientThreadLocal.get();
        logger.info("--fTPClient:"+fTPClient);
        if(fTPClient==null){
            fTPClient=getNewFTPClient();
            ftpClientThreadLocal.set(fTPClient);
        }
        else if ( fTPClient.isConnected()) {

        } else {
            fTPClient.disconnect();
            fTPClient=getNewFTPClient();
            ftpClientThreadLocal.set(fTPClient);
        }
        logger.info("--fTPClient.Status:"+fTPClient.getStatus() );
        return fTPClient;
    }

     private  FTPClient getNewFTPClient() throws Exception {
         boolean tagbool=false;
         FTPClient ftp = new FTPClient();
             logger.info("sftp connect start ========="+"hostip=="+ftpConfig.hostip+"hostport--"+ftpConfig.hostport);
             // 连接FTP服务器
             ftp.connect(ftpConfig.hostip, ftpConfig.hostport);
             logger.info("sftp connect end =========");
             // 下面三行代码必须要，而且不能改变编码格式，否则不能正确下载中文文件
             ftp.setControlEncoding("GBK");
             FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
             conf.setServerLanguageCode("zh");
             logger.info("改变编码格式结束============");
             //关闭host验证
             ftp.setRemoteVerificationEnabled(false);

             logger.info("ftp设置被动模式");
             ftp.enterLocalPassiveMode();


             // 登录ftp
             tagbool=ftp.login(ftpConfig.loginuser, ftpConfig.loginpwd);
             if(tagbool){
                 logger.info("登录ftp成功。。。。。");
             }
             else{
                 throw  new Exception("ftp 登录失败！");
             }
             // 设置部分参数和缓冲
             // 如果缺省该句 传输txt正常 但图片和其他格式的文件传输出现乱码
             tagbool=ftp.setFileType(FTP.BINARY_FILE_TYPE);
             if(tagbool){
                 logger.info("设置文件类型成功。。。。。");
             }
             else{
                 throw  new Exception("设置文件类型失败！");
             }
             ftp.setBufferSize(1024 * 1024 * 1);
             if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                 ftp.disconnect();
                 throw  new Exception("连接 FTP 服务器isPositiveCompletion失败！");
             }
             logger.info("连接 FTP 服务器isPositiveCompletion成功！");


         return  ftp;
     }

    /**
     * 关闭连接-FTP方式
     *
     */
    public boolean closeFTP( ) throws Exception {

        if (ftpClientThreadLocal!=null
                && ftpClientThreadLocal.get() != null
                && ftpClientThreadLocal.get().isConnected()) {
            FTPClient ftp = ftpClientThreadLocal.get();
            try {
                ftp.logout();
                ftp.disconnect();
                logger.info("//%%%%%%%%%断开  的fTP服务器成功！ %%%%%%%%%%%%//");
                return true;
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        return false;
    }



    /**
     * 上传文件-FTP方式  图片
     *
     * @param filrpath
     *            FTP服务器上传地址
     * @param name
     *            文件名称
     * @param inputStream
     *            输入流
     * @return boolean
     */
    public boolean uploadFile( String filrpath, String name, InputStream inputStream) throws  Exception {
        logger.info("uploadFile  开始！！！");
        boolean success = false;

        FTPClient ftp = getConnectionFTP( );
        String directory =ftpConfig.getDirectory();//.replaceAll("/",File.separator);
        String fullPath= directory+filrpath;

        logger.info("------------fullPath:" +fullPath);

        String fileName = new String(name.getBytes("GBK"), "ISO-8859-1");
        boolean cgdir =  false;

        // 转移到指定FTP服务器目录


        String pathitemList[] ;
        String tempPath="";
        pathitemList =fullPath.split("/");

        for(String pathitemname:pathitemList){
            if(StringUtil.isBlank(pathitemname))continue;
            tempPath+="/"+pathitemname;
            logger.info("-----切换目录 pathitemname ："+tempPath);
            cgdir =ftp.changeWorkingDirectory(tempPath);
            if(cgdir)  continue;

            logger.info("-----创建目录 pathitemname ："+tempPath);
            try {
                cgdir = ftp.makeDirectory(tempPath);
                cgdir = ftp.changeWorkingDirectory(tempPath);
            }catch (Exception ex){
            }
        }


        // 得到目录的相应文件列表
        // FTPFile[] fs = ftp.listFiles();
        // 防止重名！！！！！理论上不存在重名问题，以防万一
        // fileName = FtpUtil.changeName(fileName, fs);


        // 将上传文件存储到指定目录
        logger.info("-----将上传文件存储到 ：" + fullPath+"/"+fileName);
        success = ftp.storeFile( fileName, inputStream);
        // 关闭输入流
        inputStream.close();
        logger.info("//%%%%%%%%%  " + fileName + ":上传文件"+success+"！！！ %%%%%%%%%%%%//");
        return success;
    }

    /**
     * 删除文件-FTP方式
     *
     * @param syscode
     *            系统编码
     * @param filrpath
     *            FTP服务器上传地址
     * @param fileName
     *            FTP服务器上要删除的文件名
     * @return
     */
    private boolean deleteFile(String syscode,String filrpath, String fileName) throws Exception {
        FTPClient ftp = getConnectionFTP( );
        String path = ftpConfig.getDirectory() + filrpath;
        ftp.changeWorkingDirectory(path);// 转移到指定FTP服务器目录
        fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
        // path = new String(path.getBytes("GBK"), "ISO-8859-1");
        return ftp.deleteFile(fileName);
    }

    /**
     * 上传文件-FTP方式
     *
     * @param syscode
     *            系统编码
     * @param path
     *            FTP服务器上传地址
     * @param fileName
     *            本地文件路径
     * @param localPath
     *            本里存储路径
     * @return boolean
     */
//    private boolean downFile(String syscode,String path, String fileName, String localPath) throws Exception {
//
//        FtpConfig ftpConfig=getSFtpConfig(syscode);
//        FTPClient ftp = getConnectionFTP(ftpConfig);
//        boolean success = false;
//        try {
//            ftp.changeWorkingDirectory(path);// 转移到FTP服务器目录
//            FTPFile[] fs = ftp.listFiles(); // 得到目录的相应文件列表
//            for (FTPFile ff : fs) {
//                if (ff.getName().equals(fileName)) {
//                    File localFile = new File(localPath + "\\" + ff.getName());
//                    OutputStream outputStream = new FileOutputStream(localFile);
//                    // 将文件保存到输出流outputStream中
//                    ftp.retrieveFile(new String(ff.getName().getBytes("GBK"), "ISO-8859-1"), outputStream);
//                    outputStream.flush();
//                    outputStream.close();
//                    logger.info("//%%%%%%%%%  下载文件成功！！！  %%%%%%%%%%%%//");
//                }
//            }
//
//            success = true;
//        } catch (Exception e) {
//            logger.error(e.getMessage(), e);
//        }
//        return success;
//    }

    /**
     * 判断是否有重名文件
     *
     * @param fileName
     * @param fs
     * @return
     */
    private boolean isFileExist(String fileName, FTPFile[] fs) {
        for (int i = 0; i < fs.length; i++) {
            FTPFile ff = fs[i];
            if (ff.getName().equals(fileName)) {
                return true; // 如果存在返回 正确信号
            }
        }
        return false; // 如果不存在返回错误信号
    }

    /**
     * 根据重名判断的结果 生成新的文件的名称
     *
     * @param fileName
     * @param fs
     * @return
     */
    private String changeName(String fileName, FTPFile[] fs) {
        int n = 0;
        // fileName = fileName.append(fileName);
        while (isFileExist(fileName.toString(), fs)) {
            n++;
            String a = "[" + n + "]";
            int b = fileName.lastIndexOf(".");// 最后一出现小数点的位置
            int c = fileName.lastIndexOf("[");// 最后一次"["出现的位置
            if (c < 0) {
                c = b;
            }
            StringBuffer name = new StringBuffer(fileName.substring(0, c));// 文件的名字
            StringBuffer suffix = new StringBuffer(fileName.substring(b + 1));// 后缀的名称
            fileName = name.append(a) + "." + suffix;
        }
        return fileName.toString();
    }





    /**
     * 获得连接-FTP方式
     *
     *  hostname
     *            FTP服务器地址
     *  port
     *            FTP服务器端口
     *  username
     *            FTP登录用户名
     *  password
     *            FTP登录密码
     *  FTPClient
     */
    public static class  FtpConfig{
        private String id = "";
        private String hostip = "";
        private int hostport = 23;
        private String loginuser = "";
        private String loginpwd = "";
        private String insideUploadPrefix = "";
        private String outsideUploadPrefix = "";
        private String getTokenUri = "";
        private String directory;
        private String httpRootUrl;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getHttpRootUrl() {
            return httpRootUrl;
        }

        public void setHttpRootUrl(String httpRootUrl) {
            this.httpRootUrl = httpRootUrl;
        }


        public String getHostip() {
            return hostip;
        }

        public void setHostip(String hostip) {
            this.hostip = hostip;
        }

        public int getHostport() {
            return hostport;
        }

        public void setHostport(int hostport) {
            this.hostport = hostport;
        }

        public String getLoginuser() {
            return loginuser;
        }

        public void setLoginuser(String loginuser) {
            this.loginuser = loginuser;
        }

        public String getLoginpwd() {
            return loginpwd;
        }

        public void setLoginpwd(String loginpwd) {
            this.loginpwd = loginpwd;
        }

        public String getInsideUploadPrefix() {
            return insideUploadPrefix;
        }

        public void setInsideUploadPrefix(String insideUploadPrefix) {
            this.insideUploadPrefix = insideUploadPrefix;
        }

        public String getOutsideUploadPrefix() {
            return outsideUploadPrefix;
        }

        public void setOutsideUploadPrefix(String outsideUploadPrefix) {
            this.outsideUploadPrefix = outsideUploadPrefix;
        }

        public String getGetTokenUri() {
            return getTokenUri;
        }

        public void setGetTokenUri(String getTokenUri) {
            this.getTokenUri = getTokenUri;
        }

        public String getDirectory() {
            return directory;
        }

        public void setDirectory(String directory) {
            this.directory = directory;
        }
    }

}